﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Text.RegularExpressions;
using System.IO;
using System.Reflection;
using System.Diagnostics;
using System.Security.Cryptography;
using System.Net;
using System.Net.Mail;

using YouHP.Config;

namespace YouHP.Utility
{
    public class Utils
    {

        /// <summary>
        /// 得到正则编译参数设置
        /// </summary>
        /// <returns></returns>
        public static RegexOptions GetRegexCompiledOptions()
        {
#if NET1
            return RegexOptions.Compiled;
#else
            return RegexOptions.None;
#endif
        }

        public static string GetMapPath(string strPath)
        {
            if (HttpContext.Current != null)
            {
                return HttpContext.Current.Server.MapPath(strPath);
            }
            else //非web程序引用
            {
                return System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, strPath);
            }
        }

        /// <summary>
        /// 分割字符串
        /// </summary>
        public static string[] SplitString(string strContent, string strSplit)
        {
            if (strContent.IndexOf(strSplit) < 0)
            {
                string[] tmp = { strContent };
                return tmp;
            }
            return Regex.Split(strContent, @strSplit.Replace(".", @"\."), RegexOptions.IgnoreCase);
        }

        public static bool CreateDir(string name)
        {
            if(Directory.Exists(name) == false)
            {
                Directory.CreateDirectory(name);
            }
            return true;
        }

        public static string CutString(string str, int startIndex, int length)
        {
            if (startIndex >= 0)
            {
                if (length < 0)
                {
                    length = length * -1;
                    if (startIndex - length < 0)
                    {
                        length = startIndex;
                        startIndex = 0;
                    }
                    else
                    {
                        startIndex = startIndex - length;
                    }
                }


                if (startIndex > str.Length)
                {
                    return "";
                }


            }
            else
            {
                if (length < 0)
                {
                    return "";
                }
                else
                {
                    if (length + startIndex > 0)
                    {
                        length = length + startIndex;
                        startIndex = 0;
                    }
                    else
                    {
                        return "";
                    }
                }
            }

            if (str.Length - startIndex < length)
            {
                length = str.Length - startIndex;
            }

            try
            {
                return str.Substring(startIndex, length);
            }
            catch
            {
                return str;
            }
        }

        public static bool IsNumber(string strNumber)
        {
            return new Regex(@"^([0-9])[0-9]*(\.\w*)?$").IsMatch(strNumber);
        }

        public static string GetAssemblyVersion()
        {
            Assembly myAssembly = Assembly.GetExecutingAssembly();
            FileVersionInfo myFileVersion = FileVersionInfo.GetVersionInfo(myAssembly.Location);
            return string.Format("{0}.{1}.{2}", myFileVersion.FileMajorPart, myFileVersion.FileMinorPart, myFileVersion.FileBuildPart);
        }



        public static int StrToInt(object strValue, int defValue)
        {
            if ((strValue == null) || (strValue.ToString() == string.Empty))
            {
                return defValue;
            }

            int value = defValue;
            try
            {
                value = Convert.ToInt32(strValue);
            }
            catch 
            {
                value = defValue;
            }
            return value;
        }

        /// <summary>
        /// string型转换为float型
        /// </summary>
        /// <param name="strValue">要转换的字符串</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>转换后的int类型结果</returns>
        public static float StrToFloat(object strValue, float defValue)
        {
            if ((strValue == null) || (strValue.ToString() == string.Empty))
            {
                return defValue;
            }

            float value = defValue;
            try
            {
                value = Convert.ToSingle(strValue);
            }
            catch
            {
                value = defValue;
            }
            return value;           
        }

        public static double StrToDouble(object strValue, double defValue)
        {
            if ((strValue == null) || (strValue.ToString() == string.Empty))
            {
                return defValue;
            }

            double value = defValue;
            try
            {
                value = Convert.ToDouble(strValue);
            }
            catch
            {
                value = defValue;
            }
            return value;
        }


        public static bool IsIP(string ip)
        {
            return Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
        }


        public static string MD5(string str)
        {
            byte[] b = Encoding.Default.GetBytes(str);
            b = new MD5CryptoServiceProvider().ComputeHash(b);
            string ret = "";
            for (int i = 0; i < b.Length; i++)
                ret += b[i].ToString("x").PadLeft(2, '0');
            return ret;
        }

        public static string MD5(string str, int length)
        {
            string result = "";
            if (length == 16) //16位MD5加密（取32位加密的9~25字符） 
            {
                result = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(str, "MD5").ToLower().Substring(8, 16);
            }

            if (length == 32) //32位加密 
            {
                result = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(str, "MD5").ToLower();
            }

            if (length == 8) //8位MD5加密（取32位加密的9~16字符）
            {
                result = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(str, "MD5").ToLower().Substring(8, 8);
            }

            return result;
        }

        /// <summary>
        /// SHA256函数
        /// </summary>
        /// /// <param name="str">原始字符串</param>
        /// <returns>SHA256结果</returns>
        public static string SHA256(string str)
        {
            byte[] SHA256Data = Encoding.UTF8.GetBytes(str);
            SHA256Managed Sha256 = new SHA256Managed();
            byte[] Result = Sha256.ComputeHash(SHA256Data);
            return Convert.ToBase64String(Result);  //返回长度为44字节的字符串
        }


        /// <summary>
        /// 字符串如果操过指定长度则将超出的部分用指定字符串代替
        /// </summary>
        /// <param name="p_SrcString">要检查的字符串</param>
        /// <param name="p_Length">指定长度</param>
        /// <param name="p_TailString">用于替换的字符串</param>
        /// <returns>截取后的字符串</returns>
        public static string GetSubString(string p_SrcString, int p_Length, string p_TailString)
        {
            return GetSubString(p_SrcString, 0, p_Length, p_TailString);
        }


        /// <summary>
        /// 取指定长度的字符串
        /// </summary>
        /// <param name="p_SrcString">要检查的字符串</param>
        /// <param name="p_StartIndex">起始位置</param>
        /// <param name="p_Length">指定长度</param>
        /// <param name="p_TailString">用于替换的字符串</param>
        /// <returns>截取后的字符串</returns>
        public static string GetSubString(string p_SrcString, int p_StartIndex, int p_Length, string p_TailString)
        {


            string myResult = p_SrcString;

            //当是日文或韩文时(注:中文的范围:\u4e00 - \u9fa5, 日文在\u0800 - \u4e00, 韩文为\xAC00-\xD7A3)
            if (System.Text.RegularExpressions.Regex.IsMatch(p_SrcString, "[\u0800-\u4e00]+") ||
                System.Text.RegularExpressions.Regex.IsMatch(p_SrcString, "[\xAC00-\xD7A3]+"))
            {
                //当截取的起始位置超出字段串长度时
                if (p_StartIndex >= p_SrcString.Length)
                {
                    return "";
                }
                else
                {
                    return p_SrcString.Substring(p_StartIndex,
                                                   ((p_Length + p_StartIndex) > p_SrcString.Length) ? (p_SrcString.Length - p_StartIndex) : p_Length);
                }
            }


            if (p_Length >= 0)
            {
                byte[] bsSrcString = Encoding.Default.GetBytes(p_SrcString);

                //当字符串长度大于起始位置
                if (bsSrcString.Length > p_StartIndex)
                {
                    int p_EndIndex = bsSrcString.Length;

                    //当要截取的长度在字符串的有效长度范围内
                    if (bsSrcString.Length > (p_StartIndex + p_Length))
                    {
                        p_EndIndex = p_Length + p_StartIndex;
                    }
                    else
                    {   //当不在有效范围内时,只取到字符串的结尾

                        p_Length = bsSrcString.Length - p_StartIndex;
                        p_TailString = "";
                    }



                    int nRealLength = p_Length;
                    int[] anResultFlag = new int[p_Length];
                    byte[] bsResult = null;

                    int nFlag = 0;
                    for (int i = p_StartIndex; i < p_EndIndex; i++)
                    {

                        if (bsSrcString[i] > 127)
                        {
                            nFlag++;
                            if (nFlag == 3)
                            {
                                nFlag = 1;
                            }
                        }
                        else
                        {
                            nFlag = 0;
                        }

                        anResultFlag[i] = nFlag;
                    }

                    if ((bsSrcString[p_EndIndex - 1] > 127) && (anResultFlag[p_Length - 1] == 1))
                    {
                        nRealLength = p_Length + 1;
                    }

                    bsResult = new byte[nRealLength];

                    Array.Copy(bsSrcString, p_StartIndex, bsResult, 0, nRealLength);

                    myResult = Encoding.Default.GetString(bsResult);

                    myResult = myResult + p_TailString;
                }
            }

            return myResult;
        }

        public static string GetUnicodeSubString(string str, int len, string p_TailString)
        {
            string result = string.Empty;// 最终返回的结果
            int byteLen = System.Text.Encoding.Default.GetByteCount(str);// 单字节字符长度
            int charLen = str.Length;// 把字符平等对待时的字符串长度
            int byteCount = 0;// 记录读取进度
            int pos = 0;// 记录截取位置
            if (byteLen > len)
            {
                for (int i = 0; i < charLen; i++)
                {
                    if (Convert.ToInt32(str.ToCharArray()[i]) > 255)// 按中文字符计算加2
                        byteCount += 2;
                    else// 按英文字符计算加1
                        byteCount += 1;
                    if (byteCount > len)// 超出时只记下上一个有效位置
                    {
                        pos = i;
                        break;
                    }
                    else if (byteCount == len)// 记下当前位置
                    {
                        pos = i + 1;
                        break;
                    }
                }
                if (pos >= 0)
                    result = str.Substring(0, pos) + p_TailString;
            }
            else
                result = str;
            return result;
        }
        /// <summary>
        /// 根据Url获得源文件内容
        /// </summary>
        /// <param name="url">合法的Url地址</param>
        /// <returns></returns>
        public static string GetSourceTextByUrl(string url)
        {
            WebRequest request = WebRequest.Create(url);
            request.Timeout = 20000;//20秒超时
            WebResponse response = request.GetResponse();

            Stream resStream = response.GetResponseStream();
            StreamReader sr = new StreamReader(resStream);
            return sr.ReadToEnd();
        }
        /// <summary>
        /// 自定义的替换字符串函数
        /// </summary>
        public static string ReplaceString(string SourceString, string SearchString, string ReplaceString, bool IsCaseInsensetive)
        {
            return Regex.Replace(SourceString, Regex.Escape(SearchString), ReplaceString, IsCaseInsensetive ? RegexOptions.IgnoreCase : RegexOptions.None);
        }

        /// <summary>
        /// 生成指定数量的html空格符号
        /// </summary>
        public static string Spaces(int nSpaces)
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < nSpaces; i++)
            {
                sb.Append(" &nbsp;&nbsp;");
            }
            return sb.ToString();
        }

        /// <summary>
        /// 检测是否符合email格式
        /// </summary>
        /// <param name="strEmail">要判断的email字符串</param>
        /// <returns>判断结果</returns>
        public static bool IsValidEmail(string strEmail)
        {
            return Regex.IsMatch(strEmail, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
        }

        public static string GetEmailHostName(string strEmail)
        {
            if (strEmail.IndexOf("@") < 0)
            {
                return "";
            }
            return strEmail.Substring(strEmail.LastIndexOf("@")).ToLower();
        }

        public static string RemoveHtml(string content)
        {
            string regexstr = @"<[^>]*>";
            return Regex.Replace(content, regexstr, string.Empty, RegexOptions.IgnoreCase);
        }

        //autosend email
        public static bool sendMail(string destination, string Subject, string Body, bool isHtml)
        {
            BaseConfig config = BaseConfig.Instance ;

            MailAddress from = new MailAddress(config.MailServerUserName, config.MailServerDisplayName);
            MailAddress to = new MailAddress(destination);
            MailMessage message = new MailMessage(from, to);
            message.Subject = Subject;
            message.Body = Body;
            message.Priority = MailPriority.High;
            message.IsBodyHtml = isHtml;

            try
            {
                SmtpClient mailClient = new SmtpClient(config.MailServerName);
                mailClient.Credentials = new NetworkCredential(config.MailServerUserName, config.MailServerPassword);
                mailClient.Send(message);
                message.Dispose();
                return true;
            }

            catch
            {
                message.Dispose();
                return false;
            }
        }
        
        public static int GetPageCount(int count, int pageSize)
        {
            int ret =  count / pageSize ;
            if (count  % pageSize   != 0) ret++;
            return ret;
        }

        /// <summary>
        /// 获得页码显示链接
        /// </summary>
        /// <param name="curPage">当前页数</param>
        /// <param name="countPage">总页数</param>
        /// <param name="url">超级链接地址</param>
        /// <param name="extendPage">周边页码显示个数上限</param>
        /// <param name="pagetag">页码标记</param>
        /// <param name="anchor">锚点</param>
        /// <returns>页码html</returns>
        public static string GetPageNumbers(int curPage, int countPage, string url, int extendPage, string pagetag, string anchor)
        {
            if (pagetag == "")
                pagetag = "page";
            int startPage = 1;
            int endPage = 1;

            if (url.IndexOf("?") > 0)
            {
                url = url + "&";
            }
            else
            {
                url = url + "?";
            }

            string t1 = "<a href=\"" + url + "&" + pagetag + "=1";
            string t2 = "<a href=\"" + url + "&" + pagetag + "=" + countPage;
            if (anchor != null)
            {
                t1 += anchor;
                t2 += anchor;
            }
            t1 += "\">&laquo;</a>";
            t2 += "\">&raquo;</a>";

            if (countPage < 1)
                countPage = 1;
            if (extendPage < 3)
                extendPage = 2;

            if (countPage > extendPage)
            {
                if (curPage - (extendPage / 2) > 0)
                {
                    if (curPage + (extendPage / 2) < countPage)
                    {
                        startPage = curPage - (extendPage / 2);
                        endPage = startPage + extendPage - 1;
                    }
                    else
                    {
                        endPage = countPage;
                        startPage = endPage - extendPage + 1;
                        t2 = "";
                    }
                }
                else
                {
                    endPage = extendPage;
                    t1 = "";
                }
            }
            else
            {
                startPage = 1;
                endPage = countPage;
                t1 = "";
                t2 = "";
            }

            StringBuilder s = new StringBuilder("");

            s.Append(t1);
            for (int i = startPage; i <= endPage; i++)
            {
                if (i == curPage)
                {
                    s.Append("<span>");
                    s.Append(i);
                    s.Append("</span>");
                }
                else
                {
                    s.Append("<a href=\"");
                    s.Append(url);
                    s.Append(pagetag);
                    s.Append("=");
                    s.Append(i);
                    if (anchor != null)
                    {
                        s.Append(anchor);
                    }
                    s.Append("\">");
                    s.Append(i);
                    s.Append("</a>");
                }
            }
            s.Append(t2);

            return s.ToString();
        }

        /// <summary>
        /// 返回 URL 字符串的编码结果
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>编码结果</returns>
        public static string UrlEncode(string str)
        {
            return HttpUtility.UrlEncode(str);
        }

        /// <summary>
        /// 返回 URL 字符串的编码结果
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>解码结果</returns>
        public static string UrlDecode(string str)
        {
            return HttpUtility.UrlDecode(str);
        }

        #region 保存上传头像
        /// <summary>
        /// 保存上传头像
        /// </summary>
        /// <param name="MaxAllowFileSize">最大允许的头像文件尺寸(单位:KB)</param>
        /// <returns>保存文件的相对路径</returns>
        public static string SaveRequestAvatarFile(int userid, int MaxAllowFileSize)
        {
            MaxAllowFileSize *= 1024;
            string filename = Path.GetFileName(HttpContext.Current.Request.Files[0].FileName);
            if (filename == "") { return "nofile"; }
            string fileextname = Path.GetExtension(filename).ToLower();
            string filetype = HttpContext.Current.Request.Files[0].ContentType.ToLower();
            //int filesize = HttpContext.Current.Request.Files[0].ContentLength;
            // 判断 文件扩展名/文件大小/文件类型 是否符合要求
            if ((fileextname.Equals(".jpg") || fileextname.Equals(".gif") || fileextname.Equals(".png")) && (filetype.StartsWith("image")))
            {
                StringBuilder savedir = new StringBuilder();
                //savedir.Append(BaseConfigs.GetForumPath);
                savedir.Append("/Pages/youhp/Member/avatars/upload/");
                int t1 = (int)((double)userid / (double)10000);
                savedir.Append(t1);
                savedir.Append("/");
                int t2 = (int)((double)userid / (double)200);
                savedir.Append(t2);
                savedir.Append("/");
                string path =Utils.GetMapPath(savedir.ToString());
                if (!Directory.Exists(path))
                {
                    Utils.CreateDir(Utils.GetMapPath(savedir.ToString()));
                    //System.IO.Directory.CreateDirectory(Utils.GetMapPath(savedir.ToString()));
                }
                DateTime time = DateTime.Now;
                string time1 = time.ToString("yyyyMMddhhmmss");
                string newfilename = savedir.ToString() + userid.ToString()+time1 + fileextname;
                //if (System.IO.File.Exists(Utils.GetMapPath(savedir.ToString() + userid.ToString() + ".jpg")))

                if (HttpContext.Current.Request.Files[0].ContentLength <= MaxAllowFileSize)
                {
                    File.Delete(Utils.GetMapPath(savedir.ToString()) + userid.ToString() + ".jpg");
                    File.Delete(Utils.GetMapPath(savedir.ToString()) + userid.ToString() + ".gif");
                    File.Delete(Utils.GetMapPath(savedir.ToString()) + userid.ToString() + ".png");

                    HttpContext.Current.Request.Files[0].SaveAs(Utils.GetMapPath(newfilename));
                    return newfilename;
                }
            }
           return "";
        }
        #endregion

        #region 保存帖子附件
        /// <summary>
        /// 保存帖子附件
        /// </summary>
        /// <param name="MaxAllowFileSize">最大允许的附件尺寸(单位:KB)</param>
        /// <returns>保存文件的相对路径</returns>
        public static string SaveRequestTopicFile(int userid, int MaxAllowFileSize)
        {
            MaxAllowFileSize *= 1024;
            string filename = Path.GetFileName(HttpContext.Current.Request.Files[0].FileName);
            if (filename == "") { return "nofile"; }
            string fileextname = Path.GetExtension(filename).ToLower();
            string filetype = HttpContext.Current.Request.Files[0].ContentType.ToLower();
            //int filesize = HttpContext.Current.Request.Files[0].ContentLength;
            // 判断 文件扩展名/文件大小/文件类型 是否符合要求
            if ((fileextname.Equals(".jpg") 
                || fileextname.Equals(".gif")
                || fileextname.Equals(".png")
                || fileextname.Equals(".txt")
                || fileextname.Equals(".zip")
                || fileextname.Equals(".rar")) )
            {
                StringBuilder savedir = new StringBuilder();
                //savedir.Append(BaseConfigs.GetForumPath);
                savedir.Append("/Pages/youhp/Group/TopicFile/upload/");
                int t1 = (int)((double)userid / (double)10000);
                savedir.Append(t1);
                savedir.Append("/");
                int t2 = (int)((double)userid / (double)200);
                savedir.Append(t2);
                savedir.Append("/");
                string path = Utils.GetMapPath(savedir.ToString());
                if (!Directory.Exists(path))
                {
                    Utils.CreateDir(Utils.GetMapPath(savedir.ToString()));
                    //System.IO.Directory.CreateDirectory(Utils.GetMapPath(savedir.ToString()));
                }
                DateTime time = DateTime.Now;
                string time1 = time.ToString("yyyyMMddhhmmss");
                filename = filename.Replace(" ", "_");
                string newfilename = savedir.ToString() + userid.ToString() + time1 +"."+filename;
                //if (System.IO.File.Exists(Utils.GetMapPath(savedir.ToString() + userid.ToString() + ".jpg")))

                if (HttpContext.Current.Request.Files[0].ContentLength <= MaxAllowFileSize)
                {
                    File.Delete(Utils.GetMapPath(savedir.ToString()) + userid.ToString() + ".jpg");
                    File.Delete(Utils.GetMapPath(savedir.ToString()) + userid.ToString() + ".gif");
                    File.Delete(Utils.GetMapPath(savedir.ToString()) + userid.ToString() + ".png");
                    File.Delete(Utils.GetMapPath(savedir.ToString()) + userid.ToString() + ".txt");
                    File.Delete(Utils.GetMapPath(savedir.ToString()) + userid.ToString() + ".zip");
                    File.Delete(Utils.GetMapPath(savedir.ToString()) + userid.ToString() + ".rar");

                    HttpContext.Current.Request.Files[0].SaveAs(Utils.GetMapPath(newfilename));
                    return newfilename;
                }
            }
            return "";
        }
        #endregion



        /// <summary>
        /// 返回 HTML 字符串的编码结果
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>编码结果</returns>
        public static string HtmlEncode(string str)
        {
            return HttpUtility.HtmlEncode(str);
        }

        public static int[] StrToIntArray(string idstr, string spliter)
        {
            try
            {
                List<int> idlst = new List<int>();
                string[] spliterlst = new string[] { spliter };
                string[] strArray = idstr.Split(spliterlst, StringSplitOptions.RemoveEmptyEntries);
                foreach (string str in strArray)
                {
                    idlst.Add(Convert.ToInt32(str));
                }
                return idlst.ToArray();
            }
            catch 
            {
                return null;
            }
        }


        public static string RemoveQueryItem(string query, string item)
        {
            item += "=";
            int idx = query.IndexOf(item);
            if(idx < 0) return query;

            int idx2 = query.IndexOf("&",idx);
            if (idx2 < 0) return query.Substring(0, idx);
            return query.Remove(idx, idx2 - idx);
            
        }

        public static bool IsSameDate(DateTime dt1, DateTime dt2)
        {
            return (dt1.Year == dt2.Year
                && dt1.Month == dt2.Month
                && dt1.Day == dt2.Day);
        }

        public static bool WriteTextFile(string dir, string filename, string text)
        {

            if (Directory.Exists(dir) == false)
            {
                Directory.CreateDirectory(dir);
            }
            string path = Path.Combine(dir, filename);
            StreamWriter writer = new StreamWriter(path, false);
            writer.Write(text);
            writer.Close();

            return true;
        }

        public static string GetHugText(int type)
        {
            return Constants.HugBookName[type];
        }

        public static string GetHugUrl(int type)
        {
            return Constants.HugBookUrl[type];
        }
        /*得到距现在时间间隔的描述*/
        public static string GetTimeSpanStr(DateTime dateTime)
        {
            string dateDiff = null;

            TimeSpan ts1 = new TimeSpan(dateTime.Ticks);
            TimeSpan ts2 = new TimeSpan(DateTime.Now.Ticks);
            TimeSpan ts = ts1.Subtract(ts2).Duration();

    
            //dateDiff = ts.Days.ToString() + "天"
            //    + ts.Hours.ToString() + "小时"
            //    + ts.Minutes.ToString() + "分钟"
            //    + ts.Seconds.ToString() + "秒";
            if (ts.Days > 9)
            {
                dateDiff = dateTime.ToString("MM月dd日");
            }
            else if (ts.Days > 0)
            {
                dateDiff = ts.Days.ToString() + "天前";
            }
            else if (ts.Hours > 0)
            {

                dateDiff = ts.Hours.ToString() + "小时前";
            }
            else if (ts.Minutes > 0)
            {
                dateDiff = ts.Minutes.ToString() + "分钟前";
            }
            else
            {
                dateDiff = ts.Seconds.ToString() + "秒钟前";
            }

            return dateDiff;
           
        }
    }
}
